<script setup lang="ts">
import { isDev, PACS_SETTING } from '@/config/config'
import * as cornerstone from '@cornerstonejs/core'
import {
  Enums,
  metaData,
  RenderingEngine,
  setVolumesForViewports,
  Types,
  utilities,
  volumeLoader
} from '@cornerstonejs/core'
import { adaptersSEG } from '@cornerstonejs/adapters'
import { api } from 'dicomweb-client'
import { onMounted, reactive, ref, watchEffect } from 'vue'
import * as cornerstoneTools from '@cornerstonejs/tools'
import {
  SegmentationDisplayTool,
  StackScrollMouseWheelTool,
  ToolGroupManager,
  utilities as cstUtils
} from '@cornerstonejs/tools'
import { createImageIdsAndCacheMetaData, initDemo } from '@/helpers'
import FourCorner from '@/components/FourCorner.vue'
import { useFourCorner } from '@/hooks/useFourCorner'
import { DICOM_TAG_ATTR, FOUR_CORNER_SHOW_NAME } from '@/types/types'
import Controls from '@/components/Controls.vue'
import dcmjs from 'dcmjs'
import { NButton } from 'naive-ui'

const dicomlab2RGB = dcmjs.data.Colors.dicomlab2RGB

const idPrefix = 'load-segment-volume'
const uuid = utilities.uuidv4()
let renderingEngineId = `${idPrefix}-renderingEngineId-${uuid}`
let volumeId = `${idPrefix}-volumeId-${uuid}`
const viewportId = `${idPrefix}-viewportId-${uuid}`
const toolGroupId = `${idPrefix}-toolGroupId-${uuid}`
const segmentationId = 'segmentation-image-volume:' + uuid

const { ViewportType } = Enums
const { VOLUME_NEW_IMAGE } = Enums.Events
const { cornerVal, updateCornerVal } = useFourCorner([viewportId])
let renderingEngine
let imageIds
let volume
let toolGroup
let segmentationRepresentationUID
const renderContainerRef = ref(null)
const {
  segmentation,
  Enums: csToolsEnums
} = cornerstoneTools

const { SegmentationRepresentations } = csToolsEnums

async function getImageIds() {
  const params = {
    StudyInstanceUID: '1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046',
    SeriesInstanceUID: '1.3.12.2.1107.5.2.32.35162.1999123112191238897317963.0.0.0',
    wadoRsRoot: isDev() ? `/seg-dicom-web` : 'https://d33do7qe4w26qo.cloudfront.net/dicomweb'
  }
  // const params = {
  //   StudyInstanceUID: '1.2.826.0.1.3680043.2.461.13044537.2800407881',
  //   SeriesInstanceUID: '1.2.840.113619.2.472.3.2831161356.403.1654067940.232.6295553',
  //   wadoRsRoot: isDev() ? `/seg-dicom-web` : 'https://d33do7qe4w26qo.cloudfront.net/dicomweb'
  // }
  imageIds = await createImageIdsAndCacheMetaData(params)
}

const segList = ref()
let centroids

async function addSegmentationsToState() {
  const segParams = {
    studyInstanceUID: '1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046',
    seriesInstanceUID: '1.2.276.0.7230010.3.1.3.296485376.8.1542816659.201008',
    sopInstanceUID: '1.2.276.0.7230010.3.1.4.296485376.8.1542816659.201009',
    wadoRsRoot: isDev() ? `/seg-dicom-web` : 'https://d33do7qe4w26qo.cloudfront.net/dicomweb'
  }
  const arrayBuffer = await retrieveDicomData(segParams)
  const result = await adaptersSEG.Cornerstone3D.Segmentation.generateToolState(imageIds, arrayBuffer, metaData)
  centroids = result.centroids
  segList.value = result.segMetadata.data.map(item => {
    if (item && item.RecommendedDisplayCIELabValue) {
      const labValue = item.RecommendedDisplayCIELabValue
      const uniformRgb = dicomlab2RGB(labValue)
      const rgb = uniformRgb.map(each => Number.parseInt((each * 255).toString()))
      item.rgb = `rgb(${rgb[0]},${rgb[1]},${rgb[2]})`
    }
    return item
  })
  const segmentationVolume = await volumeLoader.createAndCacheDerivedSegmentationVolume(volumeId, {
    volumeId: segmentationId
  })
  const segmentationVolume1 = cornerstone.cache.getVolume(segmentationVolume.volumeId)
  segmentation.addSegmentations([
    {
      segmentationId: segmentationId,
      representation: {
        type: csToolsEnums.SegmentationRepresentations.Labelmap,
        data: {
          volumeId: segmentationId
        }
      }
    }
  ])
  const scalarData = segmentationVolume1.getScalarData()
  scalarData.set(new Uint8Array(result.labelmapBufferArray[0]))
}

function retrieveDicomData({ studyInstanceUID, seriesInstanceUID, sopInstanceUID, wadoRsRoot }) {
  const client = new api.DICOMwebClient({
    url: wadoRsRoot as string,
    singlepart: true,
    headers: PACS_SETTING.OpenAuth ? {
      'Authorization': 'Basic ' + btoa(PACS_SETTING.username + ':' + PACS_SETTING.password)
    } : {}
  })
  const options = {
    studyInstanceUID,
    seriesInstanceUID,
    sopInstanceUID
  }
  return client.retrieveInstance(options)
}

const initTools = () => {
  toolGroup = ToolGroupManager.createToolGroup(toolGroupId)
  toolGroup.addTool(StackScrollMouseWheelTool.toolName)
  toolGroup.addTool(SegmentationDisplayTool.toolName)

  toolGroup.setToolEnabled(SegmentationDisplayTool.toolName)
  toolGroup.setToolActive(StackScrollMouseWheelTool.toolName)
}

const initRender = async () => {
  renderingEngine = new RenderingEngine(renderingEngineId)
  const viewportInputArray = [{
    viewportId,
    type: ViewportType.ORTHOGRAPHIC,
    element: renderContainerRef.value,
    defaultOptions: {
      orientation: Enums.OrientationAxis.AXIAL,
      background: <Types.Point3>[0.2, 0, 0.2]
    }
  }]
  renderingEngine.setViewports(viewportInputArray)
  toolGroup.addViewport(viewportId, renderingEngineId)
  volume.load()
  await setVolumesForViewports(
    renderingEngine,
    [{ volumeId }],
    [viewportId]
  )
  const segmentationRepresentationUIDs = await segmentation.addSegmentationRepresentations(toolGroupId, [
    {
      segmentationId,
      type: csToolsEnums.SegmentationRepresentations.Labelmap
    }
  ])
  segmentationRepresentationUID = segmentationRepresentationUIDs[0]
}

async function createVolume() {
  volume = await volumeLoader.createAndCacheVolume(volumeId, {
    imageIds
  })
}

onMounted(async () => {
  await initDemo()
  initTools()
  listenEvent()
  await getImageIds()
  await createVolume()
  await addSegmentationsToState()
  await initRender()
})

const listenEvent = () => {
  (renderContainerRef.value as any).addEventListener(VOLUME_NEW_IMAGE, ((
    evt: Types.EventTypes.VolumeNewImageEvent
  ) => {
    updateCornerVal(viewportId, {
      [FOUR_CORNER_SHOW_NAME.INDEX]: evt.detail.imageIndex,
      [FOUR_CORNER_SHOW_NAME.TOTAL]: evt.detail.numberOfSlices
    })
  }) as EventListener)
}

const labelSetting = reactive({
  thickness: 1,
  outlineOpacity: 1,
  fillOpacity: 1
})

watchEffect(() => {
  segmentation.config.setToolGroupSpecificConfig(toolGroupId, {
    renderInactiveSegmentations: true,
    representations: {
      [SegmentationRepresentations.Labelmap]: {
        renderFill: true,
        renderOutline: true,
        outlineWidthActive: labelSetting.thickness,
        fillAlpha: labelSetting.fillOpacity,
        outlineOpacity: labelSetting.outlineOpacity
      }
    }
  })
})

const toggle = (item) => {
  const SegmentNumber = item.SegmentNumber
  const { x, y, z } = centroids.get(SegmentNumber)
  const viewport = renderingEngine.getViewport(viewportId)
  const centerWorld = volume.imageData.indexToWorld([x, y, z])
  cstUtils.viewport.jumpToWorld(viewport, centerWorld)

  segmentation.config.setSegmentSpecificConfig(
    toolGroupId,
    segmentationRepresentationUID,
    {
      [SegmentNumber]: {
        LABELMAP: {
          fillAlpha: 0
        }
      }
    }
  )
}
</script>

<template>
  <div class="w-full h-[600px] bg-transparent flex justify-around">
    <div class="w-[600px] h-full bg-transparent  relative" ref="renderContainerRef">
      <four-corner :fourCornerVal="cornerVal[viewportId]" />
    </div>

    <div class="w-[200px]">
      <controls
        v-model:thickness="labelSetting.thickness"
        v-model:outlineOpacity="labelSetting.outlineOpacity"
        v-model:fillOpacity="labelSetting.fillOpacity"
      />
    </div>

    <div>
      <div v-for="(item,index) in segList" :key="item">
        <template v-if="item">
          <span>{{ item.SegmentNumber }}</span>
          <span>{{ item.SegmentLabel }}</span>
          <span :style="{'backgroundColor': item.rgb}">dsfsdfsd</span>
          <n-button @click="toggle(item)">toggle</n-button>
        </template>
      </div>
    </div>
  </div>
</template>

<style scoped>

</style>
